/**
 * Copyright (C), 2015-2020, XXX有限公司
 * FileName: JsonUtils
 * Author:   zhuqifeng
 * Date:     2020/11/11 19:51
 * Description:
 * History:
 * <author>          <time>          <version>          <desc>
 * 作者姓名           修改时间           版本号              描述
 */
package com.xlkj.ms.tools.core.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * json工具类
 * @author zhuqifeng
 * @date 2021/11/10 11:58
 * @package com.xlkj.ms.tools.core.utils
 */
public class JsonUtils {

    private static Logger logger = LoggerFactory.getLogger(JsonUtils.class);

    /**
     * 判断这个key在JSONObject是否存在
     * @param json
     * @param key
     * @return
     */
    public static boolean jsonContainsKey(JSONObject json, String key){
        if(null==json){
            return false;
        }
        return json.containsKey(key);
    }

    /**
     * 判断这个key在JSONObject是否是JSONObject
     *
     * @see #thisKeyIsClass(JSONObject, String, Class)
     * @param json
     * @param key
     * @return
     */
    public static boolean thisKeyIsJsonObj(JSONObject json, String key){
        return thisKeyIsClass(json, key, JSONObject.class);
    }

    /**
     * 判断这个key在JSONObject是否是JSONArray
     *
     * @see #thisKeyIsClass(JSONObject, String, Class)
     * @param json
     * @param key
     * @return
     */
    public static boolean thisKeyIsJsonArray(JSONObject json, String key){
        return thisKeyIsClass(json, key, JSONArray.class);
    }

    /**
     * 判断JsonArray的第index个是否是JsonObject
     *
     * @see #getValueFromJsonArray(JSONArray, int, Class)
     * @param ja
     * @param index
     * @return
     */
    public static boolean thisIndexIsJsonObj(JSONArray ja, int index){
        return null!=getValueFromJsonArray(ja, index, JSONObject.class);
    }

    /**
     * 判断JsonArray的第index个是否是JsonArray
     *
     * @see #getValueFromJsonArray(JSONArray, int, Class)
     * @param ja
     * @param index
     * @return
     */
    public static boolean thisIndexIsJsonArray(JSONArray ja, int index){
        return null!=getValueFromJsonArray(ja,index, JSONArray.class);
    }

    /**
     * 判断JsonArray的第index个是否是某个类型
     *
     * @see #getValueFromJsonArray(JSONArray, int, Class)
     * @param ja
     * @param index
     * @return
     */
    public static <T> boolean thisIndexIsClass(JSONArray ja, int index, Class<T> clazz){
        return null!=getValueFromJsonArray(ja, index, clazz);
    }

    /**
     * 判断某个key对应的值是否是clazz类型
     * <pre>
     *  <strong>注意：这里的T类型是强匹配(这里可能需要关注的点是整型类型的数据结构，其他的基本没有歧义)。</strong>
     *  例1：有一串json{“abc”:123},如果thisKeyIsClass(json,key,Integer.class)出来的是true，但thisKeyIsClass(json,key,Long.class)出来的就是false
     *  例2：有一串json{“abc”:123L},如果thisKeyIsClass(json,key,Integer.class)出来的是false，但thisKeyIsClass(json,key,Long.class)出来的就是true
     *  例2：有一串json{“abc”:“123”},如果thisKeyIsClass(json,key,Integer.class)出来的是false，但thisKeyIsClass(json,key,String.class)出来的就是true
     * </pre>
     * @param json
     * @param key
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> boolean thisKeyIsClass(JSONObject json, String key, Class<T> clazz){
        if(!jsonContainsKey(json, key)){
            return false;
        }
        return clazz.isInstance(json.get(key));
    }

    /**
     * 取出这个key在JSONObject中的值（返回JSONObject）
     *
     * @see #getValueFromJsonObj(JSONObject, String, Class)
     * @param json
     * @param key
     * @return 如果不存在、不是jsonObject的返回null
     */
    public static JSONObject getJsonObjFromJsonObj(JSONObject json, String key){
        return getValueFromJsonObj(json, key, JSONObject.class);
    }

    /**
     * 取出这个key在JSONObject中的值（返回JSONArray）
     *
     * @see #getValueFromJsonObj(JSONObject, String, Class)
     * @param json
     * @param key
     * @return 如果不存在、不是jsonArray的返回null
     */
    public static JSONArray getJsonArrayFromJsonObj(JSONObject json, String key){
        return getValueFromJsonObj(json, key, JSONArray.class);
    }

    /**
     * 从json中去除key对应的int值
     *
     * @see #getValueFromJsonObj(JSONObject, String, Class)
     * @param json
     * @param key
     * @return 如果取出来是null，那么将返回-1
     */
    public static int getIntFromJsonObj(JSONObject json, String key){
        Integer value = getValueFromJsonObj(json, key, Integer.class);
        return null==value?-1:value;
    }

    /**
     * 从json中取出key对应的boolean值
     *
     * @see #getIntFromJsonObj(JSONObject, String)
     * @see #getValueFromJsonObj(JSONObject, String, Class)
     * @param json
     * @param key
     * @return
     * <pre>
     *  0\false\空\其他--返回的是false；
     *  1\true 返回true
     * </pre>
     */
    public static boolean getBoolFromJsonObj(JSONObject json, String key){
        if(thisKeyIsClass(json, key, Boolean.class)){
            return json.getBoolean(key);
        }
        int value = getIntFromJsonObj(json, key);
        return TrueOrFalse.isTrue(value);
    }

    /**
     * 从json中去除key对应的long值
     *
     * @see #getValueFromJsonObj(JSONObject, String, Class)
     * @param json
     * @param key
     * @return 如果取出来是null，那么将返回-1
     */
    public static long getLongFromJsonObj(JSONObject json, String key){
        Long value = getValueFromJsonObj(json, key, Long.class);
        return null==value?-1:value;
    }

    /**
     * 按固定的class类型获取对应的值
     * <pre>
     *  <strong>注意：这里的T类型是针对基础数据类型的弱匹配，其他类型是强匹配</strong>
     *  例1：有一串json{“abc”:123},如果getValueFromJsonObj(json,key,Integer.class)出来的是123，getValueFromJsonObj(json,key,Long.class)出来的也是123
     *  例2：有一串json{“abc”:123L},如果getValueFromJsonObj(json,key,Integer.class)出来的是123，getValueFromJsonObj(json,key,Long.class)出来的也是123
     *  例3：有一串json{“abc”:"123"},如果getValueFromJsonObj(json,key,Integer.class)出来的是123，getValueFromJsonObj(json,key,String.class)出来的也是123
     * </pre>
     * @param json
     * @param key
     * @param clazz
     * @param <T>
     * @return 异常或不存在都将返回null
     */
    public static <T> T getValueFromJsonObj(JSONObject json, String key, Class<T> clazz){
        if(!jsonContainsKey(json, key)){
            return null;
        }
        try{
            return json.getObject(key, clazz);
        }catch (Exception e){
            logger.error("获取JsonObject中的key异常{}",e.getMessage());
            return null;
        }
    }

    /**
     * 根据string解析成JSONArray
     * @param str
     * @return
     */
    public static JSONArray parseArrayByString(String str){
        if(StringUtils.isBlank(str)){
            return null;
        }
        JSONArray ja = null;
        try{
            ja = JSON.parseArray(str);
        }catch (Exception e){
            logger.error("解析JsonArray数据异常{}",e.getMessage());
        }
        return ja;
    }

    /**
     * 根据string解析成JSONObject
     * @param str
     * @return
     */
    public static JSONObject parseObjectByString(String str){
        if(StringUtils.isBlank(str)){
            return null;
        }
        JSONObject jo = null;
        try{
            jo = JSON.parseObject(str);
        }catch (Exception e){
            logger.error("解析JsonObject数据异常{}",e.getMessage());
        }
        return jo;
    }

    /**
     * 从jsonarray中获取第index个数据
     * @param ja
     * @param index
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> T getValueFromJsonArray(JSONArray ja, int index, Class<T> clazz){
        if(null==ja || ja.isEmpty()){
            return null;
        }
        if(ja.size()>index){
            try{
                return ja.getObject(index, clazz);
            }catch (Exception e){
                logger.error("获取JsonArray第index个数据异常{}",e.getMessage());
                return null;
            }
        }
        return null;
    }
}